package com.kedacom.ctsp.authz.entity;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kedacom.ctsp.lang.mapper.CollComponentType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.collections.CollectionUtils;

import java.io.Serializable;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author xuwei
 */
@EqualsAndHashCode(of = "user")
@Getter
@ToString(of = "user")
public class SimpleAuthentication implements Authentication {

    @Setter
    @Getter
    protected AuthUser user;

    @Getter
    @Setter
    protected String password;

    @Setter
    @CollComponentType(AuthRole.class)
    protected Set<AuthRole> roles;

    protected transient Set<String> roleSigns;

    /*
    @Setter
    protected Set<AuthResource> resources;

    protected transient Set<String> resourceSigns;*/

    @Setter
    @Getter
    protected AuthPerson person;

    protected Map<String, Serializable> attributes = Maps.newHashMap();

    @Override
    public Set<AuthRole> getRoles() {
        if (roles == null) {
            return Sets.newHashSet();
        } else {
            return roles;
        }
    }

    /*
    @Override
    public Set<AuthResource> getResources() {
        if (resources == null) {
            return Sets.newHashSet();
        } else {
            return resources;
        }
    }*/

    @Override
    public Set<String> getRoleSigns() {
        if (roleSigns == null) {
            if (CollectionUtils.isNotEmpty(roles)) {
                synchronized (this) {
                    roleSigns = roles.stream().map(AuthRole::getSign).collect(Collectors.toSet());
                }
            } else {
                roleSigns = Sets.newHashSet();
            }
        }
        return roleSigns;
    }

    /*@Override
    public Set<String> getResourceSigns() {
        if (resourceSigns == null) {
            if (CollectionUtils.isNotEmpty(resources)) {
                synchronized (this) {
                    resourceSigns = resources.stream().map(AuthResource::getSign).collect(Collectors.toSet());
                }
            } else {
                resourceSigns = Sets.newHashSet();
            }
        }
        return resourceSigns;
    }*/


    @Override
    public <T extends Serializable> Optional<T> getAttribute(String name) {
        return Optional.ofNullable((T) attributes.get(name));
    }


    @Override
    public void setAttribute(String name, Serializable object) {
        attributes.put(name, object);
    }

    @Override
    public void setAttributes(Map<String, Serializable> attributes) {
        this.attributes.putAll(attributes);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T extends Serializable> T removeAttributes(String name) {
        return (T) attributes.remove(name);
    }

    @Override
    public Map<String, Serializable> getAttributes() {
        return attributes;
    }
}
